﻿using System;
using System.Collections.Generic;
using UnityEngine;


public class ESF_ScriptMemPool<T> : IESF_Recycle
    where T : IESF_Recycle
{
    /// <summary>
    /// 等待取用
    /// </summary>
    private Queue<T> m_UnoccupiedPool;
    /// <summary>
    /// 正在使用的Pool
    /// </summary>
    private List<T> m_UsingPool;

    public int UsingCount { get { return m_UsingPool.Count; } }
    public int UnoccupiedCount { get { return m_UnoccupiedPool.Count; } }
  
    public ESF_ScriptMemPool() {

        m_UnoccupiedPool = new Queue<T>();
        m_UsingPool = new List<T>();
    }
    /// <summary>
    /// 归还取出的物品
    /// </summary>
    /// <param name="item"></param>
    public void GiveBack(T item) {
        if (!m_UsingPool.Remove(item))
        {
            ESF_P.ESF_Error("当前对象并非函数内自动生成！！！，检查是否有内存泄漏！！！！ ： " + item.GetType().FullName);
        }
        m_UnoccupiedPool.Enqueue(item);
    }
    public T GetItem( out bool isnew)
    {
        Type type = typeof(T);
        T uws = default;
        isnew = false;
        if (m_UnoccupiedPool.Count>0 )
        {
            uws = m_UnoccupiedPool.Dequeue();
        }
        else
        {
            bool isBaseClassInherited = type.IsSubclassOf(typeof(MonoBehaviour)); // 判断是否继承自基类
            if (isBaseClassInherited)
            {
                GameObject obj = new GameObject();
                uws = CastTo<T>(obj.AddComponent(type));
                obj.name = uws.GetHashCode().ToString();
            }
            else
            {
                uws = (T)Activator.CreateInstance(type);
            }
            isnew = true;
        }
        m_UsingPool.Add(uws);
        return uws;
    }
    private T CastTo<T>(System.Object obj) {
        return (T)obj;
    }

    /// <summary>
    /// 清除待使用的Pool
    /// </summary>
    public void ClearUnoccupiedPool() {
        for (int i = 0; i < m_UnoccupiedPool.Count; ++i)
        {
            T pool = m_UnoccupiedPool.Dequeue();
            pool.Recycle();
        }
        m_UnoccupiedPool.Clear();
    }
    /// <summary>
    /// 清除待使用的Pool
    /// </summary>
    public void Clearm_UsingPoolPool()
    {
        for (int i = 0; i < m_UsingPool.Count; ++i)
        {
            m_UsingPool[i].Recycle();
        }
        m_UsingPool.Clear();
    }
    public void Recycle()
    {
        ClearUnoccupiedPool();
        Clearm_UsingPoolPool();
        m_UnoccupiedPool = null;
        m_UsingPool = null;
    }
}
